# 常用第三方模块
# 基本上，所有的第三方模块都会在PyPI - the Python Package Index上注册，只要找到对应的模块名字，即可用pip安装。

# 1. Pillow
# PIL：Python Imaging Library，已经是Python平台事实上的图像处理标准库了。PIL功能非常强大，但API却非常简单易用。
# 由于PIL仅支持到Python 2.7，加上年久失修，于是一群志愿者在PIL的基础上创建了兼容的版本，
# 名字叫Pillow，支持最新Python 3.x，又加入了许多新特性，因此，我们可以直接安装使用Pillow。
# pip install pillow （如果遇到Permission denied安装失败，请加上sudo重试。）
import os.path
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random


def image_demo():
    # 常见的图像缩放操作：
    # 打开
    dir_path = os.path.join(".", "file")
    file_path = os.path.join(dir_path, '123.jpg')
    im = Image.open(file_path)
    w, h = im.size
    print('Original image size: %sx%s' % (w, h))
    # 缩放到50%
    im.thumbnail((w // 2, h // 2))
    print('Resize image to: %sx%s' % (w // 2, h // 2))
    # 把缩放后的图像用jpeg格式保存:

    im.save(os.path.join(dir_path, 'thumbnail.jpg'), 'jpeg')
    # 其他功能如切片、旋转、滤镜、输出文字、调色板等一应俱全。
    # 模糊效果:

    im2 = im.filter(ImageFilter.BLUR)
    im2.save(os.path.join(dir_path, 'blur.jpg'), 'jpeg')

    # PIL的ImageDraw提供了一系列绘图方法，让我们可以直接绘图。比如要生成字母验证码图片：

    # 随机字母
    def random_char():
        return chr(random.randint(65, 90))

    # 随机颜色1
    def random_color1():
        return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))

    # 随机颜色2
    def random_color2():
        return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

    # size:
    height = 60
    width = height * 4
    image = Image.new('RGB', (width, height), (255, 255, 255))
    # 创建font对象
    font = ImageFont.truetype(r'C:\Windows\Fonts\Arial.ttf', 36)
    # font = ImageFont.truetype('Arial.ttf', 36)
    # font = ImageFont.truetype('/Library/Fonts/Arial.ttf', 36)
    # 创建Draw对象
    draw = ImageDraw.Draw(image)
    # 填充每个像素
    for x in range(width):
        for y in range(height):
            draw.point((x, y), fill=random_color1())
    # 输出文字
    for t in range(4):
        draw.text((height * t + 10, 10), random_char(), font=font, fill=random_color2())
    # 模糊
    # image=image.filter(ImageFilter.BLUR)
    image.save(os.path.join(dir_path, 'auth_code.jpg'), 'jpeg')


# if __name__=='__main__':
#     image_demo()

# 2. requests
# Python内置的urllib模块，用于访问网络资源。但是，它用起来比较麻烦，而且，缺少很多实用的高级功能。
# 更好的方案是使用requests。它是一个Python第三方库，处理URL资源特别方便。
# pip install requests
import requests


def request_demo():
    # 通过GET访问一个页面
    r = requests.get('https://www.douban.com/')
    print(r.status_code)
    print(r.text)
    # 带参数的URL，传入一个dict作为params参数
    r = requests.get('https://www.douban.com/search', params={'q': 'python', 'cat': '1001'})
    print(r.url)  # 实际请求的URL
    # requests自动检测编码，可以使用encoding属性查看
    print(r.encoding)
    # 无论响应是文本还是二进制内容，我们都可以用content属性获得bytes对象：
    print(r.content)
    # requests的方便之处还在于，对于特定类型的响应，例如JSON，可以直接获取：
    r = requests.get(
        'https://dev9.hachi-tech.com/sellMedia/sellMedia/initEquipment?equipmentType=2')
    print(r.json())
    # 要传入HTTP Header时，我们传入一个dict作为headers参数：
    r = requests.get('https://www.douban.com/',
                     headers={'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'})
    print(r.text)
    # 要发送POST请求，只需要把get()方法变成post()，然后传入data参数作为POST请求的数据：
    r = requests.post('https://accounts.douban.com/login',
                      data={'form_email': 'abc@example.com', 'form_password': '123456'})
    print(r.content)
    # requests默认使用application/x-www-form-urlencoded对POST数据编码。如果要传递JSON数据，可以直接传入json参数：
    # params = {'key': 'value'}
    # r = requests.post(url, json=params) # 内部自动序列化为JSON
    # 类似的，上传文件需要更复杂的编码格式，但是requests把它简化成files参数：
    # >>> upload_files = {'file': open('report.xls', 'rb')}
    # >>> r = requests.post(url, files=upload_files)
    # 在读取文件时，注意务必使用'rb'即二进制模式读取，这样获取的bytes长度才是文件的长度。
    # 把post()方法替换为put()，delete()等，就可以以PUT或DELETE方式请求资源。
    # 除了能轻松获取响应内容外，requests对获取HTTP响应的其他信息也非常简单。例如，获取响应头：
    print('headers>>>>>>>>>', r.headers)
    # requests对Cookie做了特殊处理，使得我们不必解析Cookie就可以轻松获取指定的Cookie：
    # 要在请求中传入Cookie，只需准备一个dict传入cookies参数：
    cs = {'token': '12345', 'status': 'working'}
    r = requests.get('https://www.douban.com/', cookies=cs)
    print(r.cookies)
    print(r.cookies['bid'])
    # 最后，要指定超时，传入以秒为单位的timeout参数：
    r = requests.get('https://www.douban.com/', timeout=2.5)  # 2.5秒后超时


# if __name__=='__main__':
#     request_demo()


# 3. chardet
# 字符串编码一直是令人非常头疼的问题，尤其是我们在处理一些不规范的第三方网页的时候。虽然Python提供了Unicode表示的str和bytes两种数据类型，并且可以通过encode()和decode()方法转换，但是，在不知道编码的情况下，对bytes做decode()不好做。
# 对于未知编码的bytes，要把它转换成str，需要先“猜测”编码。猜测的方式是先收集各种编码的特征字符，根据特征字符判断，就能有很大概率“猜对”。
# 当然，我们肯定不能从头自己写这个检测编码的功能，这样做费时费力。chardet这个第三方库正好就派上了用场。用它来检测编码，简单易用
# pip install chardet
import chardet


def chardet_demo():
    # 当我们拿到一个bytes时，就可以对其检测编码
    # confidence字段，表示检测的概率是1.0（即100%）
    print(chardet.detect(b'Hello,world'))
    print(chardet.detect('abc'.encode('utf-8')))
    print(chardet.detect('中二'.encode('utf-8')))
    print(chardet.detect('中二'.encode('gbk')))
    # 检测的编码是GB2312，注意到GBK是GB2312的超集，两者是同一种编码，检测正确的概率是74%，language字段指出的语言是'Chinese'
    print(chardet.detect('离离原上草，一岁一枯荣'.encode('gbk')))
    # 试试对日文进行检测
    print(chardet.detect('最新の主要ニュース'.encode('euc-jp')))


# if __name__ == '__main__':
#     chardet_demo()


# 4. psutil
# 编写脚本简化日常的运维工作是Python的一个重要用途。在Linux下，有许多系统命令可以让我们时刻监控系统运行的状态，
# 如ps，top，free等等。要获取这些系统信息，Python可以通过subprocess模块调用并获取结果。但这样做显得很麻烦，尤其是要写很多解析代码。
# 在Python中获取系统信息的另一个好办法是使用psutil这个第三方模块。顾名思义，psutil = process and system utilities，
# 它不仅可以通过一两行代码实现系统监控，还可以跨平台使用，支持Linux／UNIX／OSX／Windows等，是系统管理员和运维小伙伴不可或缺的必备模块。
# pip install psutil
import psutil


def psutil_demo():
    print('CPU逻辑数量', psutil.cpu_count())
    print('CPU物理核心数量', psutil.cpu_count(logical=False))
    print('统计CPU的用户／系统／空闲时间：', psutil.cpu_times())
    # 再实现类似top命令的CPU使用率，每秒刷新一次，累计10次：
    # for x in range(10):
    #     print(psutil.cpu_percent(interval=1, percpu=True))
    # 获取物理内存和交换内存信息，返回的是字节为单位的整数，
    print('获取物理内存', psutil.virtual_memory())
    print('获取交换内存', psutil.swap_memory())
    print('获取磁盘分区', psutil.disk_partitions())
    print('获取磁盘使用率', psutil.disk_usage('/'))
    print('获取磁盘IO信息', psutil.disk_io_counters())
    print('获取网络读写字节／包的个数', psutil.net_io_counters())
    print('获取网络接口信息', psutil.net_if_addrs())
    print('获取网络接口状态', psutil.net_if_stats())
    print('获取当前网咯连接信息', psutil.net_connections())
    # 你可能会得到一个AccessDenied错误，原因是psutil获取信息也是要走系统接口，而获取网络连接信息需要root权限，这种情况下，可以退出Python交互环境，用sudo重新启动：
    # $ sudo python3
    print('所有进程ID', psutil.pids())
    # 获取当前Python交互环境进程
    p = psutil.Process()
    print('进程名称', p.name())
    print('进程id', p.pid)
    print('进程exe路径', p.exe())
    print('进程工作目录', p.cwd())
    print('进程启动的命令行', p.cmdline())
    print('父进程id', p.ppid)
    print('父进程', p.parent())
    print('子进程列表', p.children())
    print('进程状态', p.status())
    print('进程用户名', p.username())
    print('进程创建时间', p.create_time())
    # print('进程终端',p.terminal() )
    print('进程使用的cpu时间', p.cpu_times())
    print('进程使用的内存', p.memory_info())
    print('进程打开的文件', p.open_files())
    print('进程相关网络连接', p.connections())
    print('进程的线程数量', p.num_threads())
    print('所有线程信息', p.threads())
    print('进程环境变量', p.environ())
    # print('结束进程', p.terminate())
    # psutil还提供了一个test()函数，可以模拟出ps命令的效果：
    psutil.test()

# if __name__ == '__main__':
#     psutil_demo()

# 5.virtualenv
# 在开发Python应用程序的时候，系统安装的Python3只有一个版本：3.4。所有第三方的包都会被pip安装到Python3的site-packages目录下。
# 如果我们要同时开发多个应用程序，那这些应用程序都会共用一个Python，就是安装在系统的Python 3。如果应用A需要jinja 2.7，而应用B需要jinja 2.6怎么办？
# 这种情况下，每个应用可能需要各自拥有一套“独立”的Python运行环境。virtualenv就是用来为一个应用创建一套“隔离”的Python运行环境。
# 安装: pip3 install virtualenv
# 假定我们要开发一个新的项目，需要一套独立的Python运行环境，可以这么做：
# 第一步，创建目录：
#
# Mac:~ michael$ mkdir myproject
# Mac:~ michael$ cd myproject/
# Mac:myproject michael$
# 第二步，创建一个独立的Python运行环境，命名为venv：
#
# Mac:myproject michael$ virtualenv --no-site-packages venv
# Using base prefix '/usr/local/.../Python.framework/Versions/3.4'
# New python executable in venv/bin/python3.4
# Also creating executable in venv/bin/python
# Installing setuptools, pip, wheel...done.
# 命令virtualenv就可以创建一个独立的Python运行环境，我们还加上了参数--no-site-packages，这样，已经安装到系统Python环境中的所有第三方包都不会复制过来，这样，我们就得到了一个不带任何第三方包的“干净”的Python运行环境。
#
# 新建的Python环境被放到当前目录下的venv目录。有了venv这个Python环境，可以用source进入该环境：
#
# Mac:myproject michael$ source venv/bin/activate
# (venv)Mac:myproject michael$
# 注意到命令提示符变了，有个(venv)前缀，表示当前环境是一个名为venv的Python环境。
#
# 下面正常安装各种第三方包，并运行python命令：
#
# (venv)Mac:myproject michael$ pip install jinja2
# ...
# Successfully installed jinja2-2.7.3 markupsafe-0.23
# (venv)Mac:myproject michael$ python myapp.py
# ...
# 在venv环境下，用pip安装的包都被安装到venv这个环境下，系统Python环境不受任何影响。也就是说，venv环境是专门针对myproject这个应用创建的。
#
# 退出当前的venv环境，使用deactivate命令：
#
# (venv)Mac:myproject michael$ deactivate
# Mac:myproject michael$
# 此时就回到了正常的环境，现在pip或python均是在系统Python环境下执行。
#
# 完全可以针对每个应用创建独立的Python运行环境，这样就可以对每个应用的Python环境进行隔离。
#
# virtualenv是如何创建“独立”的Python运行环境的呢？原理很简单，就是把系统Python复制一份到virtualenv的环境，用命令source venv/bin/activate进入一个virtualenv环境时，virtualenv会修改相关环境变量，让命令python和pip均指向当前的virtualenv环境。
#
# 小结
# virtualenv为应用提供了隔离的Python运行环境，解决了不同应用间多版本的冲突问题。
